// ///////////////////////////// MIT License //////////////////////////////////// //
//                                                                                //
// Copyright (c) 2010 David Zsolt Manrique                                        //
//                    david.zsolt.manrique@gmail.com                              //
//                                                                                //
// Permission is hereby granted, free of charge, to any person obtaining a copy   //
// of this software and associated documentation files (the "Software"), to deal  //
// in the Software without restriction, including without limitation the rights   //
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell      //
// copies of the Software, and to permit persons to whom the Software is          //
// furnished to do so, subject to the following conditions:                       //
//                                                                                //
// The above copyright notice and this permission notice shall be included in     //
// all copies or substantial portions of the Software.                            //
//                                                                                //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR     //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,       //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE    //
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER         //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  //
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN      //
// THE SOFTWARE.                                                                  //
//                                                                                //
// ////////////////////////////////////////////////////////////////////////////// //


#include "structure.h"


void potential_list_t::insert(potential_base * p) 
{
	for(std::list<potential_base*>::iterator it = data.begin(); it != data.end(); ++it)
	if((**it).equivalent(*p))
	{
		delete *it; it = data.erase(it);
		if( it == data.end() ) break;
	}
	data.push_back(p); 
}

potential_list_t::~potential_list_t() { for(std::list<potential_base*>::iterator it = data.begin(); it != data.end(); it++) delete *it; }

void potential_list_t::eval(real_type & u,vector_array_type & f,const vector_array_type & r) const 
{
	for(vector_array_type::iterator it = f.begin(); it != f.end(); it++) (*it).setZero();
	u = 0.0;
	for(std::list<potential_base*>::const_iterator it = data.begin(); it != data.end(); ++it)
		(*it)->eval(u,f,r);
}
void potential_fit_list_t::peval(real_type & u,vectorx_type & dp,const vectorx_type &  p,const vector_array_type & r)
{
	dp.setZero();
	u = 0.0;
	for(std::list<potential_base*>::iterator it = data.begin(); it != data.end(); ++it)
		(*it)->peval(u,dp,p,r);
}
void potential_fit_list_t::get_parameter(vectorx_type & p)
{
	if( params.size() > 0 )  p = Eigen::VectorXd::Map(&params[0],params.size());
}

void group_t::add(const std::string & label,atom_index i) { data[label].insert(i); }
void group_t::add(const std::string & label,const std::set<atom_index> & i_set) { data[label].insert(i_set.begin(),i_set.end()); }
bool group_t::exist(const std::string & label) const { return data.find(label) != data.end(); }
const std::set<atom_index> & group_t::operator[](const std::string & label) const { return data.find(label)->second; }



void topology_t::connect(atom_index i,atom_index j)
{ function::sort(i,j); data.insert(std::pair<atom_index,atom_index>(i,j)); }
bool topology_t::connected(atom_index i,atom_index j) const
{ function::sort(i,j); return data.find(std::pair<atom_index,atom_index>(i,j)) != data.end(); }
bool topology_t::path(atom_index i,atom_index j) const
{ return connected(i,j); }
bool topology_t::path(atom_index i,atom_index j,atom_index k) const
{ return connected(i,j) && connected(j,k); }
bool topology_t::path(atom_index i,atom_index j,atom_index k,atom_index l) const
{ return path(i,j,k) && connected(k,l); }

//! It calculates the kinetic energy. Assumed that both vectors have same length.
real_type kinetic_energy(const mass_t & mass,const velocity_t & velocity)
{
	real_type k = 0.0;
	for(size_t i = 0; i < mass.size(); i++) k+=0.5*mass[i]*velocity[i].dot(velocity[i]);
	return k;
}

